package main

import (
	"encoding/json"
	"fmt"
	"os"
)

func main() {
	/*
		json包 可以实现 json 的编码和解码，就是将 json 字符串转换为 struct，或者将 struct 转换为 json。

		1.核心函数：
		（1）Marshal
			func Marshal(v interface{}) ([]byte, error)
			将 struct 编码为 json，可以接收任意类型
				当我们调用 json.Unmarshal() 函数时，我们需要传入一个指向目标数据结构的指针。
			 	函数内部会首先通过反射获取到该指针所指向的数据类型，并创建一个新的该类型的实例。
				然后，函数会遍历 JSON 数据的每个字段，查找与目标数据结构中对应字段名称相同的字段，并将值赋给该字段。
				如果在目标数据结构中找不到与之对应的字段，则忽略该字段。

				1、布尔类型 转换为 JSON 类型后仍然是 布尔类型，如 true ——> true
				2、浮点类型 和 整数类型 转换后为 JSON 里面的常规数字，如 1.23 ——> 1.23
				3、字符串将以 UTF-8 编码转化输出为 Unicode字符集的字符串，特殊字符比如 < 将会被转移为 \u003c
				4、数组和切片 被转换为 JSON 里面的数组，[]byte类 会被转换为 base64 编码后的字符串，slice的零值被转换为 null
				5、结构体 会转化为 JSON对象，并且只有结构体里面的 大写字母开头的可被导出的字段才会被转化输出，
					而这些可导出的字段会作为 JSON对象的字符串索引。
				6、转化一个 map 类型的数据结构时，该数据的类型必须是 map[string]T（T可以是 encoding/json 包）

		（2）Unmarshal
			func Unmarshal(data []byte, v interface{}) error
			将 json 转码为 struct 结构体
				这个函数会把传入的 data 作为一个 JSON 来进行解析，解析后的数据存储在参数 v 中。
			  	这个参数 v 也是任意类型的参数（但一定是一个类型的指针），原因是我们在以此函数进行 JSON 解析的时候，
			  这个函数不知道这个传入的参数的具体类型，所以我们需要它接收所有类型。

		2.核心结构：
		（1）Decoder
			Decoder 从输入流中读取并解码 JSON 值
			Decoder 可以从 io.Reader 中 或 []byte 中读取数据，并将其解析为 Go 中的数据类型。
			   具体来说，Decoder 使用 扫描器（scanner）来逐次扫描并解析其中的 JSON令牌（token），
			然后，Decoder 将这些 JSON 令牌转换为相应的 Go数据类型，并返回结果
				type Decoder struct {
					r       io.Reader
					buf     []byte
					d       decodeState
					scanp   int   // start of unread data in buf
					scanned int64 // amount of data already scanned
					scan    scanner
					err     error

					tokenState int
					tokenStack []int
				}

		（2）Encoder
			写json到输出流，应用于io流Reader Writer可以扩展到http websocket等场景。
				type Encoder struct {
					w          io.Writer
					err        error
					escapeHTML bool

					indentBuf    *bytes.Buffer
					indentPrefix string
					indentValue  string
				}

	*/
	fmt.Println("------------------------1.结构体转换为 json-------------------------")

	p := Person{
		Name:  "喜羊羊",
		Age:   18,
		Email: "xyy1234567@mail.com",
	}
	b, _ := json.Marshal(p)
	fmt.Printf("b: %v\n", string(b))
	//b: {"Name":"喜羊羊","Age":18,"Email":"xyy1234567@mail.com"}

	fmt.Println("------------------------2.解析嵌套类型------------------------------")

	p1 := Person{
		Name:   "小灰灰",
		Age:    7,
		Email:  "xhh1234567@mail.com",
		Parent: []string{"灰太狼", "红太狼"},
	}
	b, _ = json.Marshal(p1)
	fmt.Printf("b: %v\n", string(b))
	//b: {"Name":"小灰灰","Age":7,"Email":"xhh1234567@mail.com","Parent":["灰太狼","红太狼"]}

	fmt.Println("------------------------1、json 转换为结构体--------------------------")

	s := []byte(`{"Name":"孙悟空","Age":0,"Email":"swk1234567@mail.com"}`)
	var m Person
	err := json.Unmarshal(s, &m) //注：第二参数一定是 指针类型 的
	if err != nil {
		fmt.Println(err)
	}
	fmt.Printf("m: %v\n", m)
	//m: {孙悟空 0 swk1234567@mail.com []}

	fmt.Println("------------------------2、解析嵌套类型(结果为 map)----------------------------")
	s = []byte(`{"Name":"孙悟空","Age":0,"Email":"swk1234567@mail.com","Parent":["天","地"]}`)
	var m1 map[string]interface{}
	json.Unmarshal(s, &m1)
	fmt.Printf("m1: %v\n", m1)
	//m1: map[Age:0 Email:swk1234567@mail.com Name:孙悟空 Parent:[天 地]]

	for k, v := range m1 {
		fmt.Printf("k: %v v: %v\n", k, v)
	}
	/*
		k: Name v: 孙悟空
		k: Age v: 0
		k: Email v: swk1234567@mail.com
		k: Parent v: [天 地]
	*/

	fmt.Println("------------------------2、解析嵌套类型(结果为 struct)----------------------------")

	var m2 Person
	err = json.Unmarshal(s, &m2) //注：第二参数一定是 指针类型 的
	if err != nil {
		fmt.Println(err)
	}
	fmt.Printf("m: %v\n", m2)
	//m: {孙悟空 0 swk1234567@mail.com [天 地]}

	fmt.Println("------------------------------Decoder---------------------------------")

	f, _ := os.Open("喜羊羊.txt")
	defer f.Close()
	//f.Write([]byte(`{"Name":"喜羊羊","Age":18,"Email":"xyy1234567@mail.com","Parent":["智羊羊","丽羊羊"]}`))
	d := json.NewDecoder(f)
	var ma map[string]interface{}
	d.Decode(&ma)
	fmt.Printf("ma: %v\n", ma)
	//ma: map[Age:18 Email:xyy1234567@mail.com Name:喜羊羊 Parent:[智羊羊 丽羊羊]]

	fmt.Println("-------------------------------Encode(1)--------------------------------")

	p0 := Person{
		Name:   "孙悟空",
		Age:    0,
		Email:  "swk1234567@mail.com",
		Parent: []string{"天", "地"},
	}
	f, _ = os.OpenFile("水帘洞.txt", os.O_WRONLY|os.O_CREATE, 077)
	defer f.Close()

	e := json.NewEncoder(f)
	e.Encode(p0)

	fmt.Println("-------------------------------Encode(2)--------------------------------")

	// dec := json.NewDecoder(os.Stdin)
	f, _ = os.Open("水帘洞.txt")
	dec := json.NewDecoder(f)
	enc := json.NewEncoder(os.Stdout)
	for {
		var ma1 map[string]interface{}
		if err = dec.Decode(&ma1); err != nil {
			fmt.Println(err)
			return
		}
		fmt.Printf("ma1: %v\n", ma1)
		if err = enc.Encode(&ma1); err != nil { //enc.Encode(&ma1) 将 ma1 中的数据写到了标准输出中
			fmt.Println(err)
		}
	}

}

// 结构体转换为json
type Person struct {
	Name   string
	Age    int
	Email  string
	Parent []string
}
